#include "Personnage.h"
#include <string.h>
#include <assert.h>

/*======================== Gestion de la mémoire =======================*/

void initPers(Personnage* personnage, const unsigned int posX,const unsigned int posY, const unsigned int posZ)
{
   personnage->ID = 0;
   personnage->personnageSuivant = NULL;
   personnage->personnagePrecedent = NULL;
   personnage->nom = NULL;
   personnage->espece = NULL;
   personnage->compActuel = NULL;
   personnage->x = posX;
   personnage->y = posY;
   personnage->z = posZ;
   personnage->trajet = NULL;
   setCaracPers(personnage, NULL);
   setProdActPers(personnage, 0);
   setVitesseProdPers(personnage, 0);
}

void creerPersonnage(Personnage** personnage, const unsigned int posX,const unsigned int posY, const unsigned int posZ)
{
    *personnage = (Personnage*) malloc(sizeof(Personnage));
    initPers(*personnage, posX, posY, posZ);
}

void liberePers(Personnage *personnage)
{
   setNomPers(personnage, NULL);
   setEspecePers(personnage, NULL);

   if(getCarac(personnage) != NULL)
	{
	   free(personnage->carac);
	}

   if(NULL != getCompActuelPers(personnage))
	{
	   detruireCompActuel(getCompActuelPers(personnage));
	}

}


void detruirePers(Personnage* personnage)
{
   liberePers(personnage);
   free(personnage);
}

/*============================= Accesseurs =============================*/

unsigned int getIDPers(const Personnage* personnage)
{
    return personnage->ID;
}

char* getNom(const Personnage* personnage)
{
    return personnage->nom;
}

char* getEspece(const Personnage* personnage)
{
    return personnage->espece;
}

Caracteristiques* getCarac(const Personnage* personnage)
{
    return personnage->carac;
}

CompActuel *getCompActuelPers(const Personnage* personnage)
{
    return personnage->compActuel;
}


int getVitProd(const Personnage* personnage)
{
    return personnage->vitesseProd;
}

unsigned int getXPers(const Personnage* personnage)
{
    return personnage->x;
}

unsigned int getYPers(const Personnage* personnage)
{
    return personnage->y;
}

unsigned int getZPers(const Personnage* personnage)
{
    return personnage->z;
}

Personnage* getPersonnageSuivant(Personnage* personnage)
{
    return personnage->personnageSuivant;
}

Personnage* getPersonnagePrecedent(Personnage* personnage)
{
    return personnage->personnagePrecedent;
}

int getProdActPers(const Personnage *personnage)
{
   return personnage->prodAct;
}

int getVitesseProdPers(const Personnage *personnage)
{
   return personnage->vitesseProd;
}


/*============================== Mutateurs =============================*/

void setIDPers(Personnage* personnage, const unsigned int ID)
{
    personnage->ID = ID;
}

void setNomPers(Personnage* personnage, char* nom)
{
   if(NULL == nom)
	{
	   if(NULL != getNom(personnage))
		{
		   free(personnage->nom);
		}

	   personnage->nom = NULL;
	}
   else
	{
	   if(NULL != getNom(personnage))
		{
		   free(personnage->nom);
		}

	   personnage->nom = (char *)malloc((1+strlen(nom))*sizeof(char));
	   strcpy(personnage->nom, nom);
	}
}

void setEspecePers(Personnage* personnage, char* espece)
{
   if(NULL == espece)
	{
	   if(NULL != getEspece(personnage))
		{
		   free(personnage->espece);
		}

	   personnage->espece = NULL;
	}
   else
	{
	   if(NULL != getEspece(personnage))
		{
		   free(personnage->espece);
		}

	   personnage->espece = (char *)malloc((1+strlen(espece))*sizeof(char));
	   strcpy(personnage->espece, espece);
	}

}

void setCaracPers(Personnage* personnage, Caracteristiques* caracteristiques)
{
    personnage->carac = caracteristiques;
}

void setComportActuel(Personnage* personnage, CompActuel* nouvComp)
{
    personnage->compActuel = nouvComp;
}

void setXPers(Personnage* personnage, const unsigned int x)
{
    personnage->x = x;
}

void setYPers(Personnage* personnage, const unsigned int y)
{
    personnage->y = y;
}

void setZPers(Personnage* personnage, const unsigned int z)
{
    personnage->z = z;
}

void setPersonnageSuivant(Personnage* personnage, Personnage* personnageSuivant)
{
    personnage->personnageSuivant = personnageSuivant;
}

void setPersonnagePrecedent(Personnage* personnage, Personnage* personnagePrecedent)
{
    personnage->personnagePrecedent = personnagePrecedent;
}

void setProdActPers(Personnage *personnage, int nouvVal)
{
   personnage->prodAct = nouvVal;
}

void setVitesseProdPers(Personnage *personnage, int nouvVal)
{
   personnage->vitesseProd = nouvVal;
}

void setCompActuelNomCompPers(Personnage* personnage,TabComp *ptabComp, char *nomComp)
{
   CompActuel *pcompAct = getCompActuelPers(personnage);

   if(pcompAct == NULL)
	{
	   creerCompActuel(&pcompAct);
	   setComportActuel(personnage, pcompAct);
	}

   setCompNomCompActuel(pcompAct, ptabComp, nomComp);
   
}


/*========================== Fonctions autres ==========================*/

static char* genereNomPers()
{
   char* nom = "Nom";
   return nom;
}

Personnage *creerCompletPers(TabComp *ptabComp)
{
   Personnage *nouvPers;
   Caracteristiques *carac;

   creerPersonnage(&nouvPers, 1,1,0);
   setNomPers(nouvPers, genereNomPers());
   setEspecePers(nouvPers, "Nain");

   creerCaract(&carac);
   setCaracPers(nouvPers, carac);

   setCompActuelNomCompPers(nouvPers, ptabComp, "Inactif");

   return nouvPers;
}

void changementComportementPers(Personnage* personnage, Carte *pcarte, TabComp *ptabComp, Entrepot *pstock)
{
   unsigned int x,y,z;
   char *nomProd, *nomCompAct;
   CompActuel *pcompAct = getCompActuelPers(personnage);
   Comportement *pcomp;
   int modif = 1;
   int vitProd = 10;
   int valProdPers;

   x = getXPers(personnage);
   y = getYPers(personnage);
   z = getZPers(personnage);

   nomProd = getNomProdCaseCarte(pcarte, x, y, z);
   nomCompAct = getNomCompCompActuel(pcompAct);


   if (NULL != nomProd)
	{
	   /* Si le personnage est sur une case comportant une production et
	   qu'il est inactif, changer son comportement en le comportement
	   approprié à la production, puis jouer l'action */
	   if(0 == strcmp(nomCompAct, "Inactif"))
		{
		   setProdActPers(personnage, 0);
		   pcomp = rechercherCompNomProdTabComp(ptabComp, nomProd);
		   setCompActuelNomCompPers(personnage,ptabComp, getNomComp(pcomp));
		   pcompAct = getCompActuelPers(personnage);
		   executeFonctionActionCompActuel(pcompAct, pstock, pcarte, modif, x, y, z);
		}

	   else
		{
		   /* Si le personnage n'est pas inactif mais n'a pas fini de
		   récolter/construire, continuer l'action de récolte ou de
		   construction et augmenter le compteur de production du
		   personnage */
		   if(100 > getProdActPers(personnage))
			{
			   executeFonctionActionCompActuel(pcompAct, pstock, pcarte, modif, x, y, z);
			   /* Augmentation de la valeur de production du
			   personnage */
			   valProdPers = getProdActPers(personnage) + vitProd;
			   setProdActPers(personnage, valProdPers);
			}

		   /* Si le Personnage a fini de récolter/construire, passer à
		   l'action suivante, remettre le compteur à zéro, jouer
		   l'action nouvellement pointée, passer à l'action suivante */
		   else
			{
			   passeActionSuivanteCompActuel(pcompAct);
			   setProdActPers(personnage, 0);
			   executeFonctionActionCompActuel(pcompAct, pstock, pcarte, modif, x, y, z);
			   passeActionSuivanteCompActuel(pcompAct);
			}
		}
	}
   /* Si le personnage est sur une case vierge de production, passer en
   inactif s'il ne l'est pas déjà  */
   else
	{
	   if(0 != strcmp(nomCompAct, "Inactif"))
		{
		   setCompActuelNomCompPers(personnage, ptabComp, "Inactif");
		}
	}
}


/*========================== Fonction de Test ==========================*/
/**
* \brief	Teste les différentes fonctions du module Personnage
* \details	Teste les différentes fonctions du module Personnage en les
*		utilisant avec diverses valeurs plus ou moins probables
*/
void testPers()
{
   Personnage *pers;
   int i;
   TabComp *ptabComp;
   CompActuel *pcompAct;

   ptabComp = creerDonneeTabComp();

   printf("Test de Personnage\n");

   printf("\tInitialisation d'un personnage\t\t");
   creerPersonnage(&pers, 1,1,0);
   assert(0 == getProdActPers(pers));
   assert(NULL == getNom(pers));
   assert(NULL == getEspece(pers));
   printf("OK\n");

   detruirePers(pers);

   printf("\tCréation aléatoire d'un personnage\n");
   for(i = 0; i<3; i++)
	{
	   pers = creerCompletPers(ptabComp);
	   printf("\tNombre de PV du nain %d : %u\n", i, getPV(getCarac(pers)));
	   pcompAct = getCompActuelPers(pers);
	   printf("\tAction du nain %d : %s\n", i, getNomAction(getActionCompActuel(pcompAct)));
	   detruirePers(pers);
	}

   printf("\n");

   detruireTabComp(ptabComp);
}

